package com.activenetwork.util;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.openqa.selenium.WebDriver;

import com.activenetwork.custom.PageFactoryUtil;
import com.activenetwork.custom.XPageFactory;
import com.activenetwork.smlite.page.generic.PageObject;
import com.activenetwork.smlite.page.generic.PageObjectListener;
import com.google.common.collect.ImmutableSortedSet;

public class PageLoader {
	
	private static Set<XPageFactory> factories = new HashSet<XPageFactory>();
	private static List<PageObjectListener> listeners = new ArrayList<PageObjectListener>();
	
	private static Comparator<XPageFactory> comparator = new Comparator<XPageFactory>(){
		@Override
		public int compare(XPageFactory factory1, XPageFactory factory2) {
			int f1=0;
			int f2=0;
			try{
				Method m1 = factory1.getDecorator().getClass().getMethod("getDecoratorOrder");
				Method m2 = factory2.getDecorator().getClass().getMethod("getDecoratorOrder");
				f1 = (Integer)m1.invoke(factory1.getDecorator());
				f2 = (Integer)m2.invoke(factory1.getDecorator());
			}catch(Exception e){
				
			}
			return f1-f2;
		}
	};
	
//	public static Set<XPageFactory> getFactories() {
//		return factories;
//	}
//	public static void setFactories(Set<XPageFactory> factories) {
//		PageLoader.factories = factories;
//	}
	
	public static void setPageFactory(XPageFactory...factory){
		factories.addAll(Arrays.asList(factory));
	}
	
	public static void setPageObjectListener(PageObjectListener...pageObjectListeners){
		listeners.addAll(Arrays.asList(pageObjectListeners));
	}
	
	public static List<PageObjectListener> getPageObjectListener(){
		return listeners;
	}
	
	public static PageObjectListener getPageObjectListener(Class<? extends PageObjectListener> clazz){
		for(PageObjectListener listener : listeners){
			if(listener.getClass().equals(clazz)){
				return listener;
			}
		}
		throw new RuntimeException("No such page object listener loaded : " + clazz.getSimpleName());
	}
	
	public static void addException(Class<? extends PageObjectListener> listenerClazz, Class<? extends PageObject> pageObjectClazz){
		for(PageObjectListener listener : listeners){
			if(listener.getClass().equals(listenerClazz)){
				listener.addException(pageObjectClazz);
			}
		}
	}
	
	public static void removeException(Class<? extends PageObjectListener> listenerClazz, Class<? extends PageObject> pageObjectClazz){
		for(PageObjectListener listener : listeners){
			if(listener.getClass().equals(listenerClazz)){
				listener.removeException(pageObjectClazz);
			}
		}
	}
	
	/**
	 * Load by page object class
	 * @param <T>
	 * @param pageClassToProxy
	 * @return
	 */
	public static <T extends PageObject> T load(Class<T> pageClassToProxy){
		WebDriver driver = EnvContext.webDriverTL.get();
		T t = PageFactoryUtil.instantiatePage(driver, pageClassToProxy);
		ImmutableSortedSet<XPageFactory> sortedCopy = ImmutableSortedSet.copyOf(comparator, factories);
		for(XPageFactory factory : sortedCopy){
			factory.initObject(t);
		}
		for(PageObjectListener listener : listeners){
			listener.afterLoad(t);
		}
		return t;
	}
	/**
	 * Load by page object instance
	 * @param <T>
	 * @param t
	 * @return
	 */
	public static <T extends PageObject> T load(T t){
		ImmutableSortedSet<XPageFactory> sortedCopy = ImmutableSortedSet.copyOf(comparator, factories);
		for(XPageFactory factory : sortedCopy){
			factory.initObject(t);
		}
		for(PageObjectListener listener : listeners){
			listener.afterLoad(t);
		}
		return t;
	}

}
